﻿using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Legend.Object;


namespace Legend.Helper
{
    public static class Mesh
    {
        public static BoundingBox GetModelBoundingBox(Model model)
        {
            if (model == null)
            {
                throw new InvalidOperationException("model is not loaded");
            }

            float minX = float.MaxValue;
            float minY = float.MaxValue;
            float minZ = float.MaxValue;
            float maxX = float.MinValue;
            float maxY = float.MinValue;
            float maxZ = float.MinValue;

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    short positionOffset = -1;

                    foreach (VertexElement element in part.VertexDeclaration.GetVertexElements())
                    {
                        if (element.VertexElementUsage == VertexElementUsage.Position)
                        {
                            positionOffset = element.Offset;
                            break;
                        }
                    }

                    if (positionOffset >= 0)
                    {
                        Vector3[] position = new Vector3[part.NumVertices];
                        mesh.VertexBuffer.GetData(part.StreamOffset + positionOffset, position, 0, part.NumVertices, part.VertexStride);

                        foreach (Vector3 vertex in position)
                        {
                            minX = Math.Min(minX, vertex.X);
                            minY = Math.Min(minY, vertex.Y);
                            minZ = Math.Min(minZ, vertex.Z);
                            maxX = Math.Max(maxX, vertex.X);
                            maxY = Math.Max(maxY, vertex.Y);
                            maxZ = Math.Max(maxZ, vertex.Z);
                        }
                    }
                }
            }

            return new BoundingBox(new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ));
        }

        private static float Snap(float value, int snap)
        {
            if (value < 0)
            {
                value -= 0.2f;
            }
            else
            {
                value += 0.2f;
            }

            return (float)((int)(value + 0.2) - ((int)value % snap));
        }

        public static void SnapVertices(Model model, int snap)
        {
            if (model == null)
            {
                throw new InvalidOperationException("model is not loaded");
            }
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart part in mesh.MeshParts)
                {
                    short positionOffset = -1;

                    foreach (VertexElement element in part.VertexDeclaration.GetVertexElements())
                    {
                        if (element.VertexElementUsage == VertexElementUsage.Position)
                        {
                            positionOffset = element.Offset;
                            break;
                        }
                    }

                    if (positionOffset >= 0)
                    {
                        Vector3[] position = new Vector3[part.NumVertices];
                        mesh.VertexBuffer.GetData(part.StreamOffset + positionOffset, position, 0, part.NumVertices, part.VertexStride);
                        for (int i = 0; i < position.Length; ++i)
                        {
                            position[i].X = Snap(position[i].X, snap);
                            position[i].Y = Snap(position[i].Y, snap);
                            position[i].Z = Snap(position[i].Z, snap);
                        }
                        mesh.VertexBuffer.SetData(part.StreamOffset + positionOffset, position, 0, part.NumVertices, part.VertexStride);
                    }
                }
            }
        }
    }
}
